import java.io.PrintWriter;
import java.io.StringWriter;

import gui.SWTCodegGUI;

import main.AtorCompilationUnit;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Text;

import AuxComp.CompilationErrorList;

import codeg.Codeg;

public class ActorCodegGUI implements SWTCodegGUI {
    private ActorCodeg codeg;

    public void populate(final Composite content) {
        content.setLayout(new GridLayout(3, false));
        
        Label labelInitialPositionField = new Label(content, SWT.NONE);
        labelInitialPositionField.setText("Starting position:");
        
        final Label labelInitialPosition = new Label(content, SWT.NONE);
        labelInitialPosition.setText(codeg.getInitialX() + " x " + codeg.getInitialY());
        new Label(content, SWT.NONE);
        
        Label labelInitialAngleField = new Label(content, SWT.NONE);
        labelInitialAngleField.setText("Starting angle:");
        
        final Label labelInitialAngle = new Label(content, SWT.NONE);
        labelInitialAngle.setText(codeg.getInitialAngle() + " degrees");
        new Label(content, SWT.NONE);
        
        Label labelColor = new Label(content, SWT.NONE);
        labelColor.setText("Color:");
        
        final Canvas canvasColor = new Canvas(content, SWT.NONE);
        canvasColor.setBackground(colorFromCodeg(content.getDisplay(), codeg));
        GridData gd_canvas = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
        gd_canvas.heightHint = 6;
        canvasColor.setLayoutData(gd_canvas);
        new Label(content, SWT.NONE);
        
        Label lblClickOnEdit = new Label(content, SWT.NONE);
        lblClickOnEdit.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
        lblClickOnEdit.setText("Click on Edit to open, edit and verify the code");
        new Label(content, SWT.NONE);
        new Label(content, SWT.NONE);
        
        Button buttonEdit = new Button(content, SWT.NONE);
        buttonEdit.addMouseListener(new MouseAdapter() {
            public void mouseUp(MouseEvent e) {
                ActorDialog ad = new ActorDialog();
                ad.setX(codeg.getInitialX());
                ad.setY(codeg.getInitialY());
                ad.setAngle(codeg.getInitialAngle());
                ad.setColor(colorFromCodeg(content.getDisplay(), codeg));
                ad.setCode(codeg.getLocyan());
                
                ad.run(content.getDisplay());
                labelInitialPosition.setText(ad.getX() + " x " + ad.getY());
                labelInitialAngle.setText(ad.getAngle() + "degrees");
                canvasColor.setBackground(ad.getColor());
                
                codeg.setInitialX(ad.getX());
                codeg.setInitialY(ad.getY());
                codeg.setInitialAngle(ad.getAngle());
                codeg.setColor(colorToCodeg(ad.getColor()));
                codeg.setLocyan(ad.getCode());
                
                codeg.changed();
            }
        });
        buttonEdit.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        buttonEdit.setText("Edit");
    }
    
    public static Color colorFromCodeg(Display display, ActorCodeg codeg) {
        ActorCodeg.Color c =  codeg.getColor();
        return new Color(display, c.red, c.green, c.blue);
    }
    
    public static ActorCodeg.Color colorToCodeg(Color c) {
        return new ActorCodeg.Color(c.getRed(), c.getGreen(), c.getBlue());
    }
    
    public Codeg getCodeg() {
        return codeg;
    }

    public void setCodeg(Codeg codeg) {
        this.codeg = (ActorCodeg) codeg;
    }
}

class ActorDialog {
	private int x;
	private int y;
	private int angle;
	private Color color;
	private String code;
	
	public void run(Display parentDisplay) {
		final Shell shell = new Shell(parentDisplay);
		shell.setLayout(new FillLayout());
		final Composite content = new Composite(shell, SWT.NONE);
		content.setLayout(new GridLayout(5, false));
		
		Label lblDimenses = new Label(content, SWT.NONE);
		lblDimenses.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		lblDimenses.setText("Initial position: ");
		
		final Spinner spinnerX = new Spinner(content, SWT.BORDER);
		spinnerX.setMaximum(1024);
		spinnerX.setMinimum(0);
		spinnerX.setSelection(getX());
		spinnerX.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		
		Label lblPxDeAltura = new Label(content, SWT.NONE);
		lblPxDeAltura.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		lblPxDeAltura.setText("x");
		
		final Spinner spinnerY = new Spinner(content, SWT.BORDER);
		spinnerY.setMaximum(1024);
		spinnerY.setMinimum(0);
		spinnerY.setSelection(getY());
		spinnerY.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		
		Label lblPxDeLargura = new Label(content, SWT.NONE);
		lblPxDeLargura.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		lblPxDeLargura.setText("y");
		
		Label lblnguloInicial = new Label(content, SWT.NONE);
		lblnguloInicial.setText("Initial angle:");
		
		final Spinner spinnerAngle = new Spinner(content, SWT.BORDER);
		spinnerAngle.setMaximum(360);
		spinnerAngle.setMinimum(0);
		spinnerAngle.setSelection(getAngle());
		spinnerAngle.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		
		Label lblGraus = new Label(content, SWT.NONE);
		lblGraus.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
		lblGraus.setText("degrees");
		new Label(content, SWT.NONE);
		
		Label lblNewLabel = new Label(content, SWT.NONE);
		lblNewLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		lblNewLabel.setText("Color:");
		
		final Canvas canvas = new Canvas(content, SWT.NONE);
		canvas.setBackground(getColor());
		GridData gd_canvas = new GridData(SWT.FILL, SWT.FILL, false, false, 3, 1);
		gd_canvas.heightHint = 20;
		canvas.setLayoutData(gd_canvas);
		
		Button button = new Button(content, SWT.NONE);
		button.addMouseListener(new MouseAdapter() {
			public void mouseUp(MouseEvent e) {
		        ColorDialog dialog = new ColorDialog(content.getShell());
		        Color c = getColor();
		        dialog.setRGB(new RGB(c.getRed(), c.getGreen(), c.getBlue()));
		        RGB rgb = dialog.open();
		        if (rgb != null)
		            canvas.setBackground(new Color(Display.getCurrent(), rgb.red, rgb.green, rgb.blue));
			}
		});
		button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		button.setText("Select color");
		
		Label lblCdigo = new Label(content, SWT.NONE);
		lblCdigo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		lblCdigo.setText("Code:");
		
		final Text code = new Text(content, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
		code.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
		code.setText(getCode());
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		
		Button buttonCompile = new Button(content, SWT.NONE);
		buttonCompile.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		buttonCompile.setText("Compile");
		new Label(content, SWT.NONE);
		
		Label lblErros = new Label(content, SWT.NONE);
		lblErros.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		lblErros.setText("Errors:");
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		
		final Text errors = new Text(content, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
		errors.setForeground(new Color(content.getDisplay(), 255, 0, 0));
		errors.setEditable(false);
		errors.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
		buttonCompile.addMouseListener(new MouseListener() {
            public void mouseUp(MouseEvent e) {
                AtorCompilationUnit acu = new AtorCompilationUnit();
                acu.compile("", code.getText().toCharArray());
                
                StringWriter sw = new StringWriter();
                PrintWriter pwerror = new PrintWriter(sw);
                CompilationErrorList elist = acu.getCompilationErrorList();
                elist.print(pwerror);
                errors.setText(sw.toString());
            }
            public void mouseDoubleClick(MouseEvent e) {}
            public void mouseDown(MouseEvent e) {}
        });
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		new Label(content, SWT.NONE);
		
		Button buttonClose = new Button(content, SWT.NONE);
		buttonClose.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		buttonClose.setText("Close");
        buttonClose.addMouseListener(new MouseListener() {
            public void mouseUp(MouseEvent e) {
                shell.close();
                shell.dispose();
            }
            
            public void mouseDoubleClick(MouseEvent e) {}
            public void mouseDown(MouseEvent e) {}
        });
        shell.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
            	setX(spinnerX.getSelection());
            	setY(spinnerY.getSelection());
            	setAngle(spinnerAngle.getSelection());
            	setColor(canvas.getBackground());
            	setCode(code.getText());
            }
        });        
		content.pack();
		
		shell.open();
		shell.layout();
		shell.pack();
		
		shell.setSize(shell.getSize().x, 512);
		
		while (!shell.isDisposed()) {
			if (!parentDisplay.readAndDispatch()) {
			    parentDisplay.sleep();
			}
		}
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getAngle() {
		return angle;
	}

	public void setAngle(int angle) {
		this.angle = angle;
	}

	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color = color;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}
}